package com.tgpay.iot.service;

import com.tgpay.iot.config.ChargingConfig;
import com.tgpay.iot.dto.ChargingDto;
import com.tgpay.iot.entity.ChargingOrder;
import com.tgpay.iot.repository.ChargingOrderRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;

/**
 * 充电服务层
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class ChargingService {
    
    private final ChargingOrderRepository chargingOrderRepository;
    private final ChargingConfig chargingConfig;
    private final UpstreamApiService upstreamApiService;
    
    /**
     * 启动充电
     */
    @Transactional
    public ChargingDto.StartChargingResponse startCharging(ChargingDto.StartChargingRequest request) {
        // 注意：设备信息从上游API获取，不需要在本地验证设备是否存在
        
        // 先检查上游API中端口的实际状态
        try {
            Object deviceStatus = upstreamApiService.getDeviceStatus(request.getImei());
            log.debug("上游设备状态: {}", deviceStatus);
            
            // 解析上游状态，检查指定端口是否真的在充电
            boolean isPortBusy = checkPortStatusFromUpstream(deviceStatus, request.getPortId());
            
            if (isPortBusy) {
                throw new RuntimeException("该端口正在充电中");
            }
            
            // 如果上游显示端口空闲，但本地数据库显示充电中，则同步更新本地状态
            Optional<ChargingOrder> existingOrder = chargingOrderRepository
                .findByDeviceImeiAndPortIdAndStatus(request.getImei(), request.getPortId(), 1);
            
            if (existingOrder.isPresent()) {
                log.info("检测到本地订单状态与上游不一致，同步更新订单状态: {}", existingOrder.get().getOrderNo());
                ChargingOrder order = existingOrder.get();
                order.setStatus(2); // 设置为已完成
                order.setEndTime(LocalDateTime.now());
                chargingOrderRepository.save(order);
            }
            
        } catch (Exception e) {
            log.warn("获取上游设备状态失败，使用本地状态检查: {}", e.getMessage());
            
            // 如果上游API调用失败，回退到本地检查
            Optional<ChargingOrder> existingOrder = chargingOrderRepository
                .findByDeviceImeiAndPortIdAndStatus(request.getImei(), request.getPortId(), 1);
            
            if (existingOrder.isPresent()) {
                throw new RuntimeException("该端口正在充电中");
            }
        }
        
        // 验证充电参数
        if (request.getChargeType() == 2 && (request.getChargeParam() == null || request.getChargeParam() <= 0)) {
            throw new RuntimeException("按金额充电时，金额参数不能为空且必须大于0");
        }
        
        // 处理按时间充电的参数
        Integer chargeParam = request.getChargeParam();
        if (request.getChargeType() == 3) {
            if (chargeParam == null || chargeParam <= 0) {
                // 如果没有提供时间参数，使用默认值
                chargeParam = chargingConfig.getDefaultDuration();
                log.info("使用默认充电时长：{} 分钟", chargeParam);
            } else if (!chargingConfig.isValidDuration(chargeParam)) {
                // 如果提供的时间参数无效，使用有效值
                chargeParam = chargingConfig.getValidDuration(chargeParam);
                log.warn("充电时长超出范围，调整为：{} 分钟", chargeParam);
            }
        }
        
        // 先调用上游API启动充电获取订单号
        String upstreamOrderNo;
        try {
            // 构建上游API请求参数
            Map<String, Object> upstreamRequest = Map.of(
                "chargeType", request.getChargeType(),
                "chargeParam", chargeParam,
                "startMethod", request.getStartMethod(),
                "cardNumber", request.getCardNumber() != null ? request.getCardNumber() : 0,
                "availableAmount", request.getAvailableAmount() != null ? request.getAvailableAmount() : 10000
            );
            
            Object upstreamResponse = upstreamApiService.startCharging(
                request.getImei(), 
                String.valueOf(request.getPortId()), 
                upstreamRequest
            );
            
            log.info("上游API启动充电响应：{}", upstreamResponse);
            
            // 从上游响应中提取订单号
            upstreamOrderNo = extractOrderNoFromUpstreamResponse(upstreamResponse);
            
        } catch (Exception e) {
            log.error("调用上游API启动充电失败", e);
            throw new RuntimeException("启动充电失败：" + e.getMessage());
        }
        
        // 使用上游返回的订单号创建本地充电订单
        ChargingOrder order = new ChargingOrder();
        order.setOrderNo(upstreamOrderNo);
        order.setDeviceImei(request.getImei());
        order.setPortId(request.getPortId());
        order.setChargeType(request.getChargeType());
        order.setChargeParam(chargeParam);
        order.setStartMethod(request.getStartMethod());
        order.setCardNumber(request.getCardNumber());
        order.setAvailableAmount(request.getAvailableAmount());
        order.setStatus(1); // 充电中
        order.setStartTime(LocalDateTime.now());
        
        chargingOrderRepository.save(order);
        
        log.info("启动充电成功，订单号：{}", order.getOrderNo());
        
        ChargingDto.StartChargingResponse response = new ChargingDto.StartChargingResponse();
        response.setOrderNo(order.getOrderNo());
        response.setStatus(1);
        response.setMessage("充电启动成功");
        response.setStartTime(order.getStartTime());
        
        return response;
    }
    
    /**
     * 停止充电
     */
    @Transactional
    public void stopCharging(ChargingDto.StopChargingRequest request) {
        Optional<ChargingOrder> orderOpt = chargingOrderRepository.findByOrderNo(request.getOrderNo());
        
        if (orderOpt.isEmpty()) {
            throw new RuntimeException("订单不存在");
        }
        
        ChargingOrder order = orderOpt.get();
        
        if (order.getStatus() != 1) {
            throw new RuntimeException("订单状态异常，无法停止充电");
        }
        
        // 更新订单状态
        order.setStatus(2); // 已完成
        order.setEndTime(LocalDateTime.now());
        
        // 计算实际充电金额（这里简化处理，实际应根据充电时间和费率计算）
        if (order.getChargeType() == 2) {
            // 按金额充电，实际金额就是设定金额
            order.setActualAmount(order.getChargeParam());
        } else {
            // 其他类型，按时间计算（假设每分钟1分钱）
            long minutes = ChronoUnit.MINUTES.between(order.getStartTime(), order.getEndTime());
            order.setActualAmount((int) minutes);
        }
        
        chargingOrderRepository.save(order);
        
        log.info("停止充电成功，订单号：{}", order.getOrderNo());
    }
    
    /**
     * 查询充电订单
     */
    public List<ChargingOrder> getChargingOrders(String imei, Integer portId, Integer status) {
        if (status != null) {
            // 查询指定状态的订单
            return chargingOrderRepository.findByDeviceImeiAndPortIdAndStatusOrderByCreateTimeDesc(imei, portId, status);
        } else {
            // 查询所有订单
            return chargingOrderRepository.findByDeviceImeiAndPortIdOrderByCreateTimeDesc(imei, portId);
        }
    }
    
    /**
     * 获取充电状态
     */
    public ChargingDto.ChargingStatusResponse getChargingStatus(String orderNo) {
        Optional<ChargingOrder> orderOpt = chargingOrderRepository.findByOrderNo(orderNo);
        
        if (orderOpt.isEmpty()) {
            throw new RuntimeException("订单不存在");
        }
        
        ChargingOrder order = orderOpt.get();
        
        ChargingDto.ChargingStatusResponse response = new ChargingDto.ChargingStatusResponse();
        response.setOrderNo(order.getOrderNo());
        response.setStatus(order.getStatus());
        
        if (order.getStatus() == 1) {
            // 充电中，计算已充电时间
            long chargingTime = ChronoUnit.SECONDS.between(order.getStartTime(), LocalDateTime.now());
            response.setChargingTime(chargingTime);
            
            // 计算剩余时间或金额
            if (order.getChargeType() == 2) {
                // 按金额充电
                long minutes = chargingTime / 60;
                int usedAmount = (int) minutes; // 假设每分钟1分钱
                response.setRemainingAmount(Math.max(0, order.getChargeParam() - usedAmount));
            } else if (order.getChargeType() == 3) {
                // 按时间充电
                long remainingSeconds = (order.getChargeParam() * 60L) - chargingTime;
                response.setRemainingTime(Math.max(0, remainingSeconds));
            }
        } else {
            // 已完成或其他状态
            if (order.getStartTime() != null && order.getEndTime() != null) {
                long chargingTime = ChronoUnit.SECONDS.between(order.getStartTime(), order.getEndTime());
                response.setChargingTime(chargingTime);
            }
            response.setActualAmount(order.getActualAmount());
        }
        
        return response;
    }
    
    /**
     * 生成订单号
     */
    private String generateOrderNo() {
        return "CHG" + System.currentTimeMillis() + UUID.randomUUID().toString().substring(0, 8).toUpperCase();
    }
    
    /**
     * 从上游API响应中检查指定端口的状态
     */
    private boolean checkPortStatusFromUpstream(Object deviceStatus, Integer portId) {
        try {
            if (deviceStatus instanceof Map) {
                @SuppressWarnings("unchecked")
                Map<String, Object> statusMap = (Map<String, Object>) deviceStatus;
                
                // 处理嵌套的data结构
                Object data = statusMap.get("data");
                if (data instanceof Map) {
                    @SuppressWarnings("unchecked")
                    Map<String, Object> dataMap = (Map<String, Object>) data;
                    
                    // 再次检查是否有嵌套的data
                    Object innerData = dataMap.get("data");
                    if (innerData instanceof Map) {
                        @SuppressWarnings("unchecked")
                        Map<String, Object> innerDataMap = (Map<String, Object>) innerData;
                        return checkPortStatusInDataMap(innerDataMap, portId);
                    } else {
                        return checkPortStatusInDataMap(dataMap, portId);
                    }
                } else {
                    return checkPortStatusInDataMap(statusMap, portId);
                }
            }
        } catch (Exception e) {
            log.warn("解析上游设备状态失败: {}", e.getMessage());
        }
        
        // 如果解析失败，返回false（假设端口空闲）
        return false;
    }
    
    /**
     * 在数据Map中检查端口状态
     */
    private boolean checkPortStatusInDataMap(Map<String, Object> dataMap, Integer portId) {
        Object portStatus = dataMap.get("portStatus");
        if (portStatus instanceof List) {
            @SuppressWarnings("unchecked")
            List<Object> portStatusList = (List<Object>) portStatus;
            int portIndex = portId - 1; // 端口号从1开始，数组索引从0开始
            
            if (portIndex >= 0 && portIndex < portStatusList.size()) {
                Object status = portStatusList.get(portIndex);
                // 状态为1表示使用中（充电中）
                return Integer.valueOf(1).equals(status);
            }
        }
        return false;
    }
    
    /**
     * 从上游API响应中提取订单号
     */
    private String extractOrderNoFromUpstreamResponse(Object upstreamResponse) {
        try {
            if (upstreamResponse instanceof Map) {
                @SuppressWarnings("unchecked")
                Map<String, Object> responseMap = (Map<String, Object>) upstreamResponse;
                
                // 尝试从data字段中获取订单号
                Object data = responseMap.get("data");
                if (data instanceof Map) {
                    @SuppressWarnings("unchecked")
                    Map<String, Object> dataMap = (Map<String, Object>) data;
                    Object orderNo = dataMap.get("orderNo");
                    if (orderNo != null) {
                        return orderNo.toString();
                    }
                    // 也尝试orderId字段
                    Object orderId = dataMap.get("orderId");
                    if (orderId != null) {
                        return orderId.toString();
                    }
                }
                
                // 直接从响应根级别获取订单号
                Object orderNo = responseMap.get("orderNo");
                if (orderNo != null) {
                    return orderNo.toString();
                }
                Object orderId = responseMap.get("orderId");
                if (orderId != null) {
                    return orderId.toString();
                }
            }
        } catch (Exception e) {
            log.warn("从上游响应中提取订单号失败", e);
        }
        
        // 如果无法从上游响应中提取订单号，则生成一个本地订单号
        log.warn("无法从上游响应中提取订单号，使用本地生成的订单号");
        return generateOrderNo();
    }
}